1 using UnityEngine;
2 using
System.Collections;
3 using
System.Collections.Generic;
4
5
6 ///
<summary>
7 ///
base class for TweenChains and TweenFlows
8 ///
</summary>
9 public
class AbstractGoTweenCollection : AbstractGoTween
10 {
11     
protected List<TweenFlowItem> _tweenFlows = new List<TweenFlowItem>();
12     
13     
14     ///
<summary>
15     ///
data class that wraps an AbstractTween and its start time for the timeline
16     ///
</summary>
17     
protected class TweenFlowItem
18     {
19         
public float startTime;
20         
public float endTime { get { return startTime + duration; } }
21         
public float duration;
22         
public AbstractGoTween tween;
23
24
25         
public TweenFlowItem( float startTime, AbstractGoTween tween )
26         {
27             
this.tween = tween;
28             
this.startTime = startTime;
29             
this.duration = tween.totalDuration;
30         }
31         
32         
33         
public TweenFlowItem( float startTime, float duration )
34         {
35             
this.duration = duration;
36             
this.startTime = startTime;
37         }
38     }
39     
40
41     
public AbstractGoTweenCollection( GoTweenCollectionConfig config )
42     {
43         
// allow events by default
44         allowEvents =
true;
45
46         
// setup callback bools
47         _didInit =
false;
48         _didBegin =
false;
49
50         
// flag the onIterationStart event to fire.
51         
// as long as goTo is not called on this tween, the onIterationStart event will fire
52         _fireIterationStart =
true;
53
54         
// copy the TweenConfig info over
55         id = config.id;
56         loopType = config.loopType;
57         iterations = config.iterations;
58         updateType = config.propertyUpdateType;
59         timeScale =
1;
60         state = GoTweenState.Paused;
61
62         _onInit = config.onInitHandler;
63         _onBegin = config.onBeginHandler;
64         _onIterationStart = config.onIterationStartHandler;
65         _onUpdate = config.onUpdateHandler;
66         _onIterationEnd = config.onIterationEndHandler;
67         _onComplete = config.onCompleteHandler;
68
69         Go.addTween(
this );
70     }
71         
72     
73     
#region AbstractTween overrides
74     
75     ///
<summary>
76     ///
returns a list of all Tweens with the given target in the collection
77     ///
technically, this should be marked as internal
78     ///
</summary>
79     
public List<GoTween> tweensWithTarget( object target )
80     {
81         List<GoTween> list =
new List<GoTween>();
82         
83         
foreach( var flowItem in _tweenFlows )
84         {
85             
// skip TweenFlowItems with no target
86             
if( flowItem.tween == null )
87                 
continue;
88             
89             
// check Tweens first
90             
var tween = flowItem.tween as GoTween;
91             
if( tween != null && tween.target == target )
92                 list.Add( tween );
93             
94             
// check for TweenCollections
95             
if( tween == null )
96             {
97                 
var tweenCollection = flowItem.tween as AbstractGoTweenCollection;
98                 
if( tweenCollection != null )
99                 {
100                     
var tweensInCollection = tweenCollection.tweensWithTarget( target );
101                     
if( tweensInCollection.Count > 0 )
102                         list.AddRange( tweensInCollection );
103                 }
104             }
105         }
106         
107         
return list;
108     }
109     
110     
111     
public override bool removeTweenProperty( AbstractTweenProperty property )
112     {
113         
foreach( var flowItem in _tweenFlows )
114         {
115             
// skip delay items which have no tween
116             
if( flowItem.tween == null )
117                 
continue;
118             
119             
if( flowItem.tween.removeTweenProperty( property ) )
120                 
return true;
121         }
122         
123         
return false;
124     }
125     
126     
127     
public override bool containsTweenProperty( AbstractTweenProperty property )
128     {
129         
foreach( var flowItem in _tweenFlows )
130         {
131             
// skip delay items which have no tween
132             
if( flowItem.tween == null )
133                 
continue;
134             
135             
if( flowItem.tween.containsTweenProperty( property ) )
136                 
return true;
137         }
138         
139         
return false;
140     }
141     
142     
143     
public override List<AbstractTweenProperty> allTweenProperties()
144     {
145         
var propList = new List<AbstractTweenProperty>();
146         
147         
foreach( var flowItem in _tweenFlows )
148         {
149             
// skip delay items which have no tween
150             
if( flowItem.tween == null )
151                 
continue;
152             
153             propList.AddRange( flowItem.tween.allTweenProperties() );
154         }
155         
156         
return propList;
157     }

158
159     
160     ///
<summary>
161     ///
we are always considered valid because our constructor adds us to Go and we start paused
162     ///
</summary>
163     
public override bool isValid()
164     {
165         
return true;
166     }

167
168     ///
<summary>
169     ///
resumes playback
170     ///
</summary>
171     
public override void play()
172     {
173         
base.play();
174
175         
foreach( var flowItem in _tweenFlows )
176         {
177             
if( flowItem.tween != null )
178                 flowItem.tween.play();
179         }
180     }

181
182     ///
<summary>
183     ///
pauses playback
184     ///
</summary>
185     
public override void pause()
186     {
187         
base.pause();
188
189         
foreach( var flowItem in _tweenFlows )
190         {
191             
if( flowItem.tween != null )
192                 flowItem.tween.pause();
193         }
194     }

195     
196     ///
<summary>
197     ///
tick method. if it returns true it indicates the tween is complete
198     ///
</summary>
199     
public override bool update( float deltaTime )
200     {
201         
if ( !_didInit )
202             onInit();
203
204         
if ( !_didBegin )
205             onBegin();
206
207         
if ( _fireIterationStart )
208             onIterationStart();
209
210         
// update the timeline and state.
211         
base.update( deltaTime );
212
213         
// get the proper elapsedTime if we're doing a PingPong
214         
var convertedElapsedTime = _isLoopingBackOnPingPong ? duration - _elapsedTime : _elapsedTime;
215
216         
// used for iterating over flowItems below.
217         TweenFlowItem flowItem =
null;
218
219         
// if we iterated last frame and this flow restarts from the beginning, we now need to reset all
220         
// of the flowItem tweens to either the beginning or the end of their respective timelines
221         
// we also want to do this in the _opposite_ way that we would normally iterate on them
222         
// as the start value of a later flowItem may alter a property of an earlier flowItem.
223         
if ( _didIterateLastFrame && loopType == GoLoopType.RestartFromBeginning )
224         {
225             
if ( isReversed || _isLoopingBackOnPingPong )
226             {
227                 
for ( int i = 0; i < _tweenFlows.Count; ++i )
228                 {
229                     flowItem = _tweenFlows[i];
230
231                     
if ( flowItem.tween == null )
232                         
continue;
233
234                     
var cacheAllow = flowItem.tween.allowEvents;
235                     flowItem.tween.allowEvents =
false;
236                     flowItem.tween.restart();
237                     flowItem.tween.allowEvents = cacheAllow;
238                 }
239             }
240             
else
241             {
242                 
for ( int i = _tweenFlows.Count - 1; i >= 0; --i )
243                 {
244                     flowItem = _tweenFlows[i];
245
246                     
if ( flowItem.tween == null )
247                         
continue;
248
249                     
var cacheAllow = flowItem.tween.allowEvents;
250                     flowItem.tween.allowEvents =
false;
251                     flowItem.tween.restart();
252                     flowItem.tween.allowEvents = cacheAllow;
253                 }
254             }
255         }
256         
else
257         {
258             
if ( ( isReversed && !_isLoopingBackOnPingPong ) || ( !isReversed && _isLoopingBackOnPingPong ) )
259             {
260                 
// if we are moving the tween in reverse, we should be iterating over the flowItems in reverse
261                 
// to help properties behave a bit better.
262                 
for ( var i = _tweenFlows.Count - 1; i >= 0; --i )
263                 {
264                     flowItem = _tweenFlows[i];
265
266                     
if ( flowItem.tween == null )
267                         
continue;
268
269                     
// if there's been an iteration this frame and we're not done yet, we want to make sure
270                     
// this tween is set to play in the right direction, and isn't set to complete/paused.
271                     
if ( _didIterateLastFrame && state != GoTweenState.Complete )
272                     {
273                         
if ( !flowItem.tween.isReversed )
274                             flowItem.tween.reverse();
275
276                         flowItem.tween.play();
277                     }
278
279                     
if ( flowItem.tween.state == GoTweenState.Running && flowItem.endTime >= convertedElapsedTime )
280                     {
281                         
var convertedDeltaTime = Mathf.Abs( convertedElapsedTime - flowItem.startTime - flowItem.tween.totalElapsedTime );
282                         flowItem.tween.update( convertedDeltaTime );
283                     }
284                 }
285             }
286             
else
287             {
288                 
for ( int i = 0; i < _tweenFlows.Count; ++i )
289                 {
290                     flowItem = _tweenFlows[i];
291
292                     
if ( flowItem.tween == null )
293                         
continue;
294
295                     
// if there's been an iteration this frame and we're not done yet, we want to make sure
296                     
// this tween is set to play in the right direction, and isn't set to complete/paused.
297                     
if ( _didIterateLastFrame && state != GoTweenState.Complete )
298                     {
299                         
if ( flowItem.tween.isReversed )
300                             flowItem.tween.reverse();
301
302                         flowItem.tween.play();
303                     }
304
305                     
if ( flowItem.tween.state == GoTweenState.Running && flowItem.startTime <= convertedElapsedTime )
306                     {
307                         
var convertedDeltaTime = convertedElapsedTime - flowItem.startTime - flowItem.tween.totalElapsedTime;
308                         flowItem.tween.update( convertedDeltaTime );
309                     }
310                 }
311             }
312         }
313
314         onUpdate();
315
316         
if ( _fireIterationEnd )
317             onIterationEnd();
318
319         
if ( state == GoTweenState.Complete )
320         {
321             onComplete();
322
323             
return true; // true if complete
324         }
325
326         
return false; // false if not complete
327     }

328
329     ///
<summary>
330     ///
reverses playback. if going forward it will be going backward after this and vice versa.
331     ///
</summary>
332     
public override void reverse()
333     {
334         
base.reverse();
335
336         
var convertedElapsedTime = _isLoopingBackOnPingPong ? duration - _elapsedTime : _elapsedTime;
337
338         
foreach ( var flowItem in _tweenFlows )
339         {
340             
if ( flowItem.tween == null )
341                 
continue;
342
343             
if ( isReversed != flowItem.tween.isReversed )
344                 flowItem.tween.reverse();
345
346             flowItem.tween.pause();
347
348             
// we selectively mark tweens for play if they will be played immediately or in the future.
349             
// update() will filter out more tweens that should not be played yet.
350             
if ( isReversed || _isLoopingBackOnPingPong )
351             {
352                 
if ( flowItem.startTime <= convertedElapsedTime )
353                     flowItem.tween.play();
354             }
355             
else
356             {
357                 
if ( flowItem.endTime >= convertedElapsedTime )
358                     flowItem.tween.play();
359             }
360         }
361     }

362
363     ///
<summary>
364     ///
goes to the specified time clamping it from 0 to the total duration of the tween. if the tween is
365     ///
not playing it will be force updated to the time specified.
366     ///
</summary>
367     
public override void goTo( float time, bool skipDelay = true )
368     {
369         time = Mathf.Clamp( time,
0f, totalDuration );
370
371         
// provide an early out for calling goTo on the same time multiple times.
372         
if ( time == _totalElapsedTime )
373             
return;
374
375         
// we don't simply call base.goTo because that would force an update within AbstractGoTweenCollection,
376         
// which forces an update on all the tweenFlowItems without putting them in the right position.
377         
// it's also possible that people will move around a tween via the goTo method, so we want to
378         
// try to make that as efficient as possible.
379
380         
// if we are doing a goTo at the "start" of the timeline, based on the isReversed variable,
381         
// allow the onBegin and onIterationStart callback to fire again.
382         
// we only allow the onIterationStart event callback to fire at the start of the timeline,
383         
// as doing a goTo(x) where x % duration == 0 will trigger the onIterationEnd before we
384         
// go to the start.
385         
if ( ( isReversed && time == totalDuration ) || ( !isReversed && time == 0f ) )
386         {
387             _didBegin =
false;
388             _fireIterationStart =
true;
389         }
390         
else
391         {
392             _didBegin =
true;
393             _fireIterationStart =
false;
394         }
395
396         
// since we're doing a goTo, we want to stop this tween from remembering that it iterated.
397         
// this could cause issues if you caused the tween to complete an iteration and then goTo somewhere
398         
// else while still paused.
399         _didIterateThisFrame =
false;
400
401         
// force a time and completedIterations before we update
402         _totalElapsedTime = time;
403         _completedIterations = isReversed ? Mathf.CeilToInt( _totalElapsedTime / duration ) : Mathf.FloorToInt( _totalElapsedTime / duration );
404
405         
// we don't want to use the Collection update function, because we don't have all of our
406         
// child tweenFlowItems setup properly. this will properly setup our iterations,
407         
// totalElapsedTime, and other useful information.
408         
base.update( 0 );
409
410         
var convertedElapsedTime = _isLoopingBackOnPingPong ? duration - _elapsedTime : _elapsedTime;
411
412         
// we always want to process items in the future of this tween from last to first.
413         
// and items that have already occured from first to last.
414         TweenFlowItem flowItem =
null;
415         
if ( isReversed || _isLoopingBackOnPingPong )
416         {
417             
// flowItems in the future of the timeline
418             
for ( int i = 0; i < _tweenFlows.Count; ++i )
419             {
420                 flowItem = _tweenFlows[i];
421
422                 
if ( flowItem == null )
423                     
continue;
424
425                 
if ( flowItem.endTime >= convertedElapsedTime )
426                     
break;
427
428                 changeTimeForFlowItem( flowItem, convertedElapsedTime );
429             }
430
431             
// flowItems in the past & current part of the timeline
432             
for ( int i = _tweenFlows.Count - 1; i >= 0; --i )
433             {
434                 flowItem = _tweenFlows[i];
435
436                 
if ( flowItem == null )
437                     
continue;
438
439                 
if ( flowItem.endTime < convertedElapsedTime )
440                     
break;
441
442                 changeTimeForFlowItem( flowItem, convertedElapsedTime );
443             }
444         }
445         
else
446         {
447             
// flowItems in the future of the timeline
448             
for ( int i = _tweenFlows.Count - 1; i >= 0; --i )
449             {
450                 flowItem = _tweenFlows[i];
451
452                 
if ( flowItem == null )
453                     
continue;
454
455                 
if ( flowItem.startTime <= convertedElapsedTime )
456                     
break;
457
458                 changeTimeForFlowItem( flowItem, convertedElapsedTime );
459             }
460
461             
// flowItems in the past & current part of the timeline
462             
for ( int i = 0; i < _tweenFlows.Count; ++i )
463             {
464                 flowItem = _tweenFlows[i];
465
466                 
if ( flowItem == null )
467                     
continue;
468
469                 
if ( flowItem.startTime > convertedElapsedTime )
470                     
break;
471
472                 changeTimeForFlowItem( flowItem, convertedElapsedTime );
473             }
474         }
475     }
476
477     
private void changeTimeForFlowItem( TweenFlowItem flowItem, float time )
478     {
479         
if ( flowItem == null || flowItem.tween == null )
480             
return;
481
482         
if ( flowItem.tween.isReversed != ( isReversed || _isLoopingBackOnPingPong ) )
483             flowItem.tween.reverse();
484
485         
var convertedTime = Mathf.Clamp( time - flowItem.startTime, 0f, flowItem.endTime );
486
487         
if ( flowItem.startTime <= time && flowItem.endTime >= time )
488         {
489             flowItem.tween.goToAndPlay( convertedTime );
490         }
491         
else
492         {
493             flowItem.tween.goTo( convertedTime );
494             flowItem.tween.pause();
495         }
496     }
497
498     
#endregion
499     
500 }



Trò chơi Angry Birds trong UNITY Engine 31.722 lượt xem

Gõ tìm kiếm nhanh...